﻿using System;
using System.Drawing;
using System.Windows.Forms;

using Microsoft.Drawing;

using Spencen.Mobile.UI.Primitives;
using Spencen.Mobile.UI.Commanding;

namespace Spencen.Mobile.UI.Controls
{
    public class GlassButton : RectangleElement, ICommandSource
    {
        private bool _isPressed;
        
        public GlassButton()
        {
            Font = new Font( FontFamily.GenericSansSerif, 11.0f, FontStyle.Regular );
            Foreground = new SolidBrush( Color.White );
            CanFocus = true;
        }

        public string Text { get; set; }
        public Font Font { get; set; }
        public Brush Foreground { get; set; }
        public ICommand Command { get; set; }
        public bool IsPressed { get { return _isPressed; } set { _isPressed = value; Invalidate(); } }

        protected override void OnRender( GraphicsContext context )
        {
            var points = GeneratePoints();

            points = context.TransformedPoints( points );

            var fullRect = new Rectangle( points[ 0 ].X, points[ 0 ].Y, points[ 2 ].X - points[ 0 ].X, points[ 2 ].Y - points[ 0 ].Y );
            if ( fullRect.Width <= 2 || fullRect.Height <= 2 ) return; // Short circuit to prevent zero rect exceptions

            DrawGlass( context, points, 240, GlassTheme.DarkGlass );

            var textBounds = context.Graphics.MeasureString( Text, Font );

            context.Graphics.DrawString( Text, Font, Foreground, 
                new RectangleF(
                    fullRect.X + fullRect.Width / 2 - textBounds.Width / 2,
                    fullRect.Top + fullRect.Height / 2 - textBounds.Height / 2, 
                    textBounds.Width,
                    textBounds.Height ) );

            //context.Graphics.FillGradientRectangle( bottomRect, Color.FromArgb( 0, 0, 0 ), Color.FromArgb( 128, 128, 128 ), FillDirection.TopToBottom );

            context.Graphics.FillRectangle( new SolidBrush( Color.FromArgb( 133, 133, 133 ) ),
                fullRect.X, fullRect.Y, fullRect.Width, 2 );

            context.Graphics.DrawRectangle( new Pen( Color.Black ), fullRect );
            fullRect.Inflate( -1, -1 );
            context.Graphics.DrawRectangle( new Pen( Color.Gray ), fullRect );
            //context.Graphics.DrawPolygon( Stroke, points );

            if ( HasFocus )
            {
                fullRect.Inflate( -1, -1 );
                context.Graphics.DrawRectangle( context.FocusPen, fullRect );
            }
        }

        public static void DrawGlass( GraphicsContext context, Point[] points, byte opacity, GlassTheme glassTheme )
        {
            var topRect = new Rectangle( points[ 0 ].X, points[ 0 ].Y, points[ 2 ].X - points[ 0 ].X, ( points[ 2 ].Y - points[ 0 ].Y ) / 3 );
            var bottomRect = new Rectangle( points[ 0 ].X, topRect.Bottom, points[ 2 ].X - points[ 0 ].X, ( points[ 2 ].Y - points[ 0 ].Y ) / 3 * 2 );

            if ( topRect.Height <= 1 || topRect.Width <= 1 ) return;

            Bitmap glassTop;
            Bitmap glassBottom;

            switch ( glassTheme )
            {
                case GlassTheme.DarkGlass:
                    glassTop = GraphicsExtension.GetGradientRectangle(
                        new Rectangle( 0, 0, topRect.Width, topRect.Height ),
                        Color.FromArgb( 76, 76, 76 ), Color.FromArgb( 47, 47, 47 ), FillDirection.TopToBottom );
                    break;

                case GlassTheme.LightGlass:
                default:
                    glassTop = GraphicsExtension.GetGradientRectangle(
                        new Rectangle( 0, 0, topRect.Width, topRect.Height ),
                        Color.FromArgb( 255, 255, 255 ), Color.FromArgb( 239, 239, 239 ), FillDirection.TopToBottom );
                    break;
            }

            context.Graphics.DrawAlpha( glassTop, opacity, topRect.X, topRect.Y );

            switch ( glassTheme )
            {
                case GlassTheme.DarkGlass:
                    glassBottom = GraphicsExtension.GetGradientRectangle(
                        new Rectangle( 0, 0, bottomRect.Width, bottomRect.Height ),
                        Color.FromArgb( 29, 29, 29 ), Color.FromArgb( 34, 34, 34 ), FillDirection.TopToBottom );
                    break;

                case GlassTheme.LightGlass:
                default:
                    glassBottom = GraphicsExtension.GetGradientRectangle(
                        new Rectangle( 0, 0, bottomRect.Width, bottomRect.Height ),
                        Color.FromArgb( 221, 221, 221 ), Color.FromArgb( 173, 173, 173 ), FillDirection.TopToBottom );
                    break;
            }

            context.Graphics.DrawAlpha( glassBottom, opacity, bottomRect.X, bottomRect.Y );

            glassTop.Dispose();
            glassBottom.Dispose();
        }

        protected override void OnResize()
        {
            base.OnResize();
            
            if ( Font != null ) Font.Dispose();

            float optimumSize = Size.Height / 5.0f;

            Font = new Font( FontFamily.GenericSansSerif, optimumSize, FontStyle.Regular );
        }

        #region Interaction Logic

        // This is required whilst the contents is rendered entirely in OnRender and not via child elements.
        public override bool HitTest( Point hitPoint, GraphicsContext context )
        {
            return DrawingSupport.PolygonContains( GeneratePoints(), hitPoint );
        }

        protected internal override void OnMouseDown( MouseEventArgs e )
        {
            base.OnMouseDown( e );
            IsPressed = true;
        }

        protected internal override void OnMouseUp( MouseEventArgs e )
        {
            base.OnMouseUp( e );

            // TODO: Check that mouse is still within the bounds of the control
            OnClick();
            IsPressed = false;
        }

        public event EventHandler Click;

        protected virtual void OnClick()
        {
            if ( Command != null )
                Command.Execute();

            var handler = Click;
            if ( handler != null )
                handler( this, EventArgs.Empty );
        }

        #endregion
    }

    public enum GlassTheme
    {
        LightGlass,
        DarkGlass
    }
}
